#ifndef CORE_WL_H
#define CORE_WL_H
#pragma once
#include <QObject>
#include <QDebug>
#include <QRect>
#include <QDateTime>

#include <gst/gst.h>
#include <pulse/pulseaudio.h>
#include <gbm.h>
#include <unistd.h>
#include <signal.h>
#include <sstream>
#include <sys/mman.h>
#include <xf86drm.h>
#include <iostream>
#include <thread>

#include <wayland-client-protocol.h>
#include "core_wl/protocol/wlr-screencopy-unstable-v1-client-protocol.h"
#include "core_wl/protocol/xdg-output-unstable-v1-client-protocol.h"
#include "core_wl/protocol/linux-dmabuf-unstable-v1-client-protocol.h"
#include "core_wl/frame-writer.hpp"
#include "core_wl/buffer-pool.hpp"
#include "core_wl/config.h"
#include "global/global.h"
#include "utils/desktopinfo.h"
#include "utils/confighandler.h"
#include "core/devices.h"

class Core_wl : public QObject
{
    Q_OBJECT
public:

    //wayland协议中的输出设备
    struct wf_recorder_output           // 输出设备的相关信息
    {
        wl_output *output;              //Wayland 协议中的输出设备对象，表示一个物理显示器
        zxdg_output_v1 *zxdg_output;    //XDG 输出协议中的输出设备对象
        std::string name, description;  //设备的名称
        int32_t x, y, width, height;
    };
    struct capture_region               //捕获区域
    {
        int32_t x, y;
        int32_t width, height;

        capture_region()
            : capture_region(0, 0, 0, 0) {}

        capture_region(int32_t _x, int32_t _y, int32_t _width, int32_t _height)
            : x(_x), y(_y), width(_width), height(_height) { }

        void set_from_string(std::string geometry_string)
        {
            if (sscanf(geometry_string.c_str(), "%d,%d %dx%d", &x, &y, &width, &height) != 4)
            {
                fprintf(stderr, "Bad geometry: %s, capturing whole output instead.\n",
                    geometry_string.c_str());
                x = y = width = height = 0;
                return;
            }
        }

        bool is_selected()
        {
            return width > 0 && height > 0;
        }

        bool contained_in(const capture_region& output) const
        {
            return
                output.x <= x &&
                output.x + output.width >= x + width &&
                output.y <= y &&
                output.y + output.height >= y + height;
        }
    };
    struct wf_buffer : public buffer_pool_buf   //帧缓存池
    {
        struct gbm_bo *bo = nullptr;
        zwp_linux_buffer_params_v1 *params = nullptr;
        struct wl_buffer *wl_buffer = nullptr;
        void *data = nullptr;
        size_t size = 0;
        enum wl_shm_format format;
        int drm_format;
        int width, height, stride;
        bool y_invert;

        timespec presented;
        uint64_t base_usec;
//        /* 析构
        ~wf_buffer() {
//                 1. 释放 wl_buffer
                if (wl_buffer) {
                    wl_buffer_destroy(wl_buffer);
                    wl_buffer = nullptr;
                    qDebug()<<"wl_buffer 释放";
                }

//                 2. 销毁 Linux DMA-BUF 参数
                if (params) {
                    zwp_linux_buffer_params_v1_destroy(params);
                    params = nullptr;
                    qDebug()<<"params 释放";
                }

                // 3. 释放 GBM 对象
                if (bo) {
                    gbm_bo_destroy(bo);
                    bo = nullptr;
                    qDebug()<<"bo 释放";
                }

//                 4. 清理映射的内存（如果是 SHM）
                if (data) {
                    munmap(data, size);  // 需要 #include <sys/mman.h>
                    data = nullptr;
                    size = 0;
                    qDebug()<<"data 释放";
                }
            }
//*/
    };
    //wayland注册回调函数-用于全局变量的初始化
    static void handle_global(void*, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t);
    static void handle_global_remove(void*, struct wl_registry *, uint32_t);
    static void dmabuf_feedback_done(void *, struct zwp_linux_dmabuf_feedback_v1 *feedback);
    static void dmabuf_feedback_format_table(void *, struct zwp_linux_dmabuf_feedback_v1 *, int32_t fd, uint32_t);
    static void dmabuf_feedback_main_device(void *, struct zwp_linux_dmabuf_feedback_v1 *, struct wl_array *device);
    static void dmabuf_feedback_tranche_done(void *, struct zwp_linux_dmabuf_feedback_v1 *);
    static void dmabuf_feedback_tranche_target_device(void *, struct zwp_linux_dmabuf_feedback_v1 *, struct wl_array *);
    static void dmabuf_feedback_tranche_formats(void *, struct zwp_linux_dmabuf_feedback_v1 *, struct wl_array *);
    static void dmabuf_feedback_tranche_flags(void *, struct zwp_linux_dmabuf_feedback_v1 *, uint32_t);
    static void handle_xdg_output_logical_position(void*, zxdg_output_v1* zxdg_output, int32_t x, int32_t y);
    static void handle_xdg_output_logical_size(void*, zxdg_output_v1* zxdg_output, int32_t w, int32_t h);
    static void handle_xdg_output_done(void*, zxdg_output_v1*);
    static void handle_xdg_output_name(void*, zxdg_output_v1 *zxdg_output_v1, const char *name);
    static void handle_xdg_output_description(void*, zxdg_output_v1 *zxdg_output_v1, const char *description);
    static void frame_handle_buffer(void *, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height, uint32_t stride);
    static void frame_handle_flags(void*, struct zwlr_screencopy_frame_v1 *, uint32_t flags);
    static void frame_handle_ready(void *, struct zwlr_screencopy_frame_v1 *, uint32_t tv_sec_hi, uint32_t tv_sec_low, uint32_t tv_nsec);
    static void frame_handle_failed(void *, struct zwlr_screencopy_frame_v1 *);
    static void frame_handle_damage(void *, struct zwlr_screencopy_frame_v1 *, uint32_t, uint32_t, uint32_t, uint32_t);
    static void frame_handle_linux_dmabuf(void *, struct zwlr_screencopy_frame_v1 *frame, uint32_t format, uint32_t width, uint32_t height);
    static void frame_handle_buffer_done(void *, struct zwlr_screencopy_frame_v1 *);
    static void dmabuf_created(void *data, struct zwp_linux_buffer_params_v1 *, struct wl_buffer *wl_buffer);
    static void dmabuf_failed(void *, struct zwp_linux_buffer_params_v1 *);

    static Core_wl *getInstance();
    explicit Core_wl(QObject *parent = nullptr);
    ~Core_wl();

    //初始参数设置
    void setPropertyOfSelectWid(uint qId, bool isfullscreen, bool isWindow, QString screen, uint id, QRect rect, double scale);
    void setSavePath(QString savePath);
    void setSaveFormat(QString saveformat);
    void setResolution(int resolution);
    void setFrameRate(QString frameRate);
    void setMicrophone(QString microphone);
    void setEncoderAndAudioCodec();

    //系统音频和麦克风
    void getSysDevices(QStringList &ls, QString soundtype = "monitor", bool isName = false);        //获取系统音频设备
    void getMicDevices(QStringList &ls, QString soundtype = "monitor", bool isName = false);        //获取麦克风设备
    QString getUsingMicDevices(bool isName = false);                                    //获取录屏正在使用的麦克风设备
    QString getUsingSysDevices(bool isName = false);                                    //获取系统音频设备
    void openMicrophone();
    void closeMicrophone();
    void toggle_microphone(bool mute);
    void levelMeterStart(QString name);                         //检测麦克风音量
    static gboolean message_handler( GstBus * bus, GstMessage * message, gpointer data );
    void ModifylevelMeterDevice (QString newDevice);            //更改检测的麦克风设置
    QStringList getAllDevices();
    bool isAvailable();

    //录制
    bool startRecord();                                         //开始录制
    void stopRecord(QString &completePath);                     //停止录制
    void pauseRecord();
    void contineRecord();

signals:
    void updateVolume(int newVolume);

private:
    bool initWayland();         //初始化 Wayland 连接
    void sync_wayland();        //同步wayland事件
    bool check_has_protos();    //wayland协议检查
    void load_output_info();    //加载输出信息
    bool user_specified_overwrite(std::string filename);        //检查用户是否允许覆盖指定文件
    wf_recorder_output* detect_output_from_region(const capture_region& region);
    wf_recorder_output* choose_interactive();
    static void handle_graceful_termination(int);
    static void request_next_frame();
    static void parse_codec_opts(std::map<std::string, std::string>& options, const std::string param);
    void write_loop(FrameWriterParams params);                  //帧写入
    uint64_t timespec_to_usec (const timespec& ts);
    InputFormat get_input_format(wf_buffer& buffer);
    static uint32_t wl_shm_to_drm_format(uint32_t format);
    static wl_buffer *create_shm_buffer(uint32_t fmt, int width, int height, int stride, void **data_out);
    static int backingfile(off_t size);
    static wl_shm_format drm_to_wl_shm_format(uint32_t format);
    static void free_shm_buffer(wf_buffer& buffer);

    void handleEvents();    // 处理 Wayland 事件
    void cleanup();         // 清理资源

    // wayland注册与回调
    wl_display *m_display = nullptr;        //wayland显示
    wl_registry *m_registry = nullptr;
    //录制
    bool spawned_thread = false;
    std::thread writer_thread;
    std::atomic<bool> is_paused{false};     //录制是否暂停
    uint64_t pause_start = 0;               //暂停开始时间
    uint64_t pause_duration = 0;            //暂停总时长
    //保存参数设置
    int m_x=0, m_y=0, m_width=200, m_height=100;
    QString m_videoPath;        //保存路径
    QString m_completePathRec;  //保存路径+文件名
    QString m_formatString;     //保存类型
    SaveFormat m_format;
    QString m_codec;            //视频编码
    QString m_audioCodec;       //音频编码
    double m_bitrate = 8000;
    int m_qpmin = 8;            //视频质量
    int m_qpmax = 8;
    int m_fps = 25;             //帧率
    int m_keyframe_dist = 128;
    int m_deadline = 10000;
    //麦克风
    QString m_microphoneName = "";              //选择的麦克风
    QString m_NoMic = tr("none mic");
    QHash<QString, QString> mapNameToDevice;    //麦克风：名字-设备
    bool m_closeMicrophone = false;             //关闭麦克风
    QList<GstElement *> m_micSourceList;        //麦克风源
    GstElement *pipelineMic = nullptr;          //音量的
    pa_mainloop* m_mainloop = nullptr;
    pa_context* m_context = nullptr;
    //桌面信息
    DesktopInfo m_info;
};

#endif // CORE_WL_H
